#include "cartoonnet.h"

CartoonNet::CartoonNet (const std::string modelpath, std::string id) {
    net = dnn::readNetFromONNX (modelpath.c_str ());
    net.setPreferableBackend (dnn::DNN_BACKEND_OPENCV);
    net.setPreferableTarget (dnn::DNN_TARGET_CPU);

    name = id;
    std::cout << modelpath << " 模型加载成功！" << std::endl;
}

CartoonNet::~CartoonNet () {}

/**
 * 输入尺寸必须和模型要求尺寸一致
 */
void CartoonNet::Run (const Mat &input,Mat& output) {
    int height = input.rows;
    int width = input.cols;
    int channels = input.channels ();
    Mat output;
    printf ("height: %d width: %d\n", input.rows, input.cols);
    int     sizes[3] = {height, width, channels};
    cv::Mat blob (3, sizes, CV_32FC1);

    for (int y = 0; y < height; y++) {
        const uchar *src = input.ptr<uchar> (y);
        float       *dst = blob.ptr<float> (y);
        for (int x = 0; x < width; x++) {
            dst[0] = src[0];
            dst[1] = src[1];
            dst[2] = src[2];
            dst += 3;
            src += 3;
        }
    }
    net.setInput (blob);
    try {
// Mat out;
//  获取所有层名称
#if 0
        std::vector<std::string> layerNames = net.getLayerNames ();

        // 逐层计时
        std::cout << "Layer-wise timing:" << std::endl;
        for (int i = 0;i < layerNames.size();i++) {
            //std::vector<std::string> targetLayers;
            //targetLayers.push_back(layerNames[i]);
            cv::TickMeter           tm;

            tm.start ();
            net.forward (layerNames[i]);
            tm.stop ();

            std::cout << "Layer " << layerNames[i] << ": " << tm.getTimeMilli () << " ms" << std::endl;
        }
#endif
        Mat out;
        net.forward (out, "output_image");

        if (!out.empty ()) {
            output.create (height, width, CV_8UC3);
            const float *src = out.ptr<float> ();
            uchar       *dst = output.ptr<uchar> ();
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    dst[0] = src[0];
                    dst[1] = src[1];
                    dst[2] = src[2];
                    dst += 3;
                    src += 3;
                }
            }
        }

    } catch (const cv::Exception &e) {
        std::cout << "推理失败，错误信息：" << e.what () << std::endl;
    }
}

#ifdef DEBUG_CARTOONNET
int main (int argc, char *argv[]) {
    CartoonNet cn ("model/anime/cartoon_h.onnx");
    Mat        image = imread ("out1.jpg");
    if (image.empty ()) {
        std::cerr << "无法加载图像" << std::endl;
        return -1;
    }
    Mat out = cn.Run (image);
    imwrite ("cartoon_h1.jpg", out);
    return 0;
}
#endif
// g++ -std=c++11 cartoonnet.cpp -o cartoon_h -DDEBUG_CARTOONNET=1
// -I/home/android/opencv/build/install/usr/local/include/opencv4 -L/home/android/opencv/build/install/usr/local/lib
// -lopencv_dnn_objdetect -lopencv_dnn_superres -lopencv_shape -lopencv_highgui -lopencv_xobjdetect -lopencv_objdetect
// -lopencv_imgcodecs -lopencv_dnn -lopencv_imgproc -lopencv_core
//  export LD_LIBRARY_PATH=/home/android/opencv/build/install/usr/local/lib
